package cn.edu.neu.vmmigeval.cloud.policy.impl;


import cn.edu.neu.vmmigeval.cloud.config.Migration;
import cn.edu.neu.vmmigeval.cloud.entity.Host;
import cn.edu.neu.vmmigeval.cloud.entity.Vm;
import cn.edu.neu.vmmigeval.cloud.policy.MigratedHostPolicy;
import cn.edu.neu.vmmigeval.cloud.policy.VmPlacementPolicy;

import java.util.ArrayList;
import java.util.List;


public class VmPlacementPolicyDefault extends VmPlacementPolicy {
	
	private double threshold;
	
	public VmPlacementPolicyDefault(List<Host> hostList,
			MigratedHostPolicy migratedHostPolicy) {
		super(hostList, migratedHostPolicy);
	}
	public VmPlacementPolicyDefault(double threshold){
		this.threshold = threshold;
	}
	@Override
	public List<Migration> getNewVmPlacement(List<Vm> vmsToMigrate,List<Host> hosts) {
		
		List<Migration> migs = new ArrayList<Migration>();
		for (Vm vm : vmsToMigrate) {
			Host targetHost = findHostForVm(vm, getExcludedHosts(hosts),threshold);
			if (targetHost != null) {
				Host srcHost = vm.getHost();
				vm.setInMigration(true);
				List<Vm> vms = new ArrayList<Vm>();
				vms.add(vm);
				Migration migration = new Migration();
				migration.setSrcHost(srcHost);
				migration.setDestHost(targetHost);
				migration.setVms(vms);
				migration.setClocks((int)((vm.getCurrentRam()/(targetHost.getTotalBw()-targetHost.getCurrentBw()+10)))+1);
			//	System.out.println("clocks is :"+migration.getClocks());
				migration.setEnd(false);
				
				srcHost.setMigration(true);
				srcHost.setMigrationIn(2);
				srcHost.setActive(0);
				
				targetHost.setMigration(true);
				targetHost.setActive(0);
				targetHost.setMigrationIn(1);
				migs.add(migration);
			}
		}
		return migs;
	}
	
	public List<Host> getExcludedHosts(List<Host> hosts){
		
		List<Host> excludedHosts = new ArrayList<Host>();
		for (Host host : hosts) {
			if(!host.isMigration()){//host.getActive()==0&&
				excludedHosts.add(host);
			}
		}
		return excludedHosts;
		
		
	}
	
	public Host findHostForVm(Vm vm, List<Host> excludedHosts,double threshold){
		
		//System.out.println("hello world;");
		for (Host host : excludedHosts) {
			int cpu = 0,ram = 0 ,bw=0,disk=0;
			List<Vm> vms = host.getVmList();
			if(vms!=null&&vms.size()!=0){
				if(host.getActive()==1){
					System.out.println("--������");
				}
				
				for (Vm vm2 : vms) {
					cpu+=vm2.getTotalCpu();
					ram+=vm2.getTotalRam();
					bw+=vm2.getTotalBw();
					disk+=vm2.getTotalDisk();
				}
				if(((vm.getTotalCpu()+cpu)<=host.getTotalCpu())&&((vm.getTotalRam()+ram)<=host.getTotalRam())
						&&((vm.getTotalBw()+bw)<=host.getTotalBw())&&((vm.getTotalDisk()+disk)<=host.getTotalDisk())){
					
					if((double)(vm.getCurrentCpu()+host.getCurrentCpu())/host.getTotalCpu()<=threshold){
						return host;
					}
				}
			}else{
				//System.out.println("select");
				return host;
			}
		}
		return null;
	}
	public double getThreshold() {
		return threshold;
	}
	public void setThreshold(double threshold) {
		this.threshold = threshold;
	}
	
	
	

}
